/*
 * Copyright (c) 2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.libermundi.theorcs.core.tapestry.services.impl;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.libermundi.theorcs.core.exceptions.EmailException;
import org.libermundi.theorcs.core.model.Account;
import org.libermundi.theorcs.core.model.freemarker.FreemarkerEmail;
import org.libermundi.theorcs.core.tapestry.services.FreemarkerEmailService;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.google.common.collect.Lists;

public class FreemarkerEmailServiceImpl implements FreemarkerEmailService {
	
	private final JavaMailSender _mailSender;
	
	private final Map<String, FreemarkerEmail> _emails;
	
	private final ThreadPoolTaskExecutor _executor;

	public FreemarkerEmailServiceImpl(JavaMailSender mailSender, Map<String, FreemarkerEmail> emails, ThreadPoolTaskExecutor executor) {
		_mailSender = mailSender;
		_emails = emails;
		_executor = executor;
	}
	
	/* (non-Javadoc)
	 * @see org.libermundi.theorcs.core.tapestry.services.EmailService#sendEmail(java.lang.String, java.util.Map, org.libermundi.theorcs.core.model.Account)
	 */
	@Override
	public void sendEmail(String emailId, Map<String, Object> parameters,
			Account to) throws EmailException {
		Account[] tos = { to };
		sendEmail(emailId, parameters, Arrays.asList(tos), null, null);
	}

	/* (non-Javadoc)
	 * @see org.libermundi.theorcs.core.tapestry.services.EmailService#sendEmail(java.lang.String, java.util.Map, java.util.List)
	 */
	@Override
	public void sendEmail(String emailId, Map<String, Object> parameters,
			List<Account> to) throws EmailException {
		sendEmail(emailId, parameters, to, null, null);
	}

	/* (non-Javadoc)
	 * @see org.libermundi.theorcs.core.tapestry.services.EmailService#sendEmail(java.lang.String, java.util.Map, java.util.List, java.util.List)
	 */
	@Override
	public void sendEmail(String emailId, Map<String, Object> parameters,
			List<Account> to, List<Account> cc) throws EmailException {
		sendEmail(emailId, parameters, to, cc, null);
	}

	/* (non-Javadoc)
	 * @see org.libermundi.theorcs.core.tapestry.services.EmailService#sendEmail(java.lang.String, java.util.Map, java.util.List, java.util.List, java.util.List)
	 */
	@Override
	public void sendEmail(final String emailId, final Map<String, Object> parameters, List<Account> to, List<Account> cc, List<Account> bcc)
			throws EmailException {
		FreemarkerEmail email = _emails.get(emailId);
		MimeMessage mimeMessage = _mailSender.createMimeMessage();
		MimeMessageHelper message = email.getMailMessage(mimeMessage, parameters);
		
		List<InternetAddress> toEmails = Lists.newArrayList();
		List<InternetAddress> ccEmails = Lists.newArrayList();
		List<InternetAddress> bccEmails = Lists.newArrayList();
		
		try {
			for (Account account : to) {
				toEmails.add(new InternetAddress(account.getEmail()));
			}
			message.setTo(transformToArray(toEmails));
			
			if (cc != null && !cc.isEmpty()) {
				for (Account account : cc) {
					ccEmails.add(new InternetAddress(account.getEmail()));
				}
				message.setCc(transformToArray(ccEmails));
			}
			
			if (bcc != null && !bcc.isEmpty()) {
				for (Account account : bcc) {
					bccEmails.add(new InternetAddress(account.getEmail()));
				}
				message.setBcc(transformToArray(bccEmails));
			}				
		} catch(MessagingException e) {
			throw new EmailException(e.getMessage());
		}

		_executor.submit(new SendMail(message));
		
	}
	
	private static InternetAddress[] transformToArray(List<InternetAddress> input){
		return input.toArray(new InternetAddress[input.size()]);
	}
	
	private class SendMail extends Thread {
		private MimeMessageHelper messageHelper;

	    SendMail(MimeMessageHelper messageHelper) {
	        this.messageHelper = messageHelper;
	    }

	    @Override
	    public void run() {
	        _mailSender.send(messageHelper.getMimeMessage());
	    }

	}

}
